/*****************************************************************************
*   sys.c:  source file for system control
*		ver 2.0
******************************************************************************/

#include "me32g030.h"
#include "system_me32g030.h"
#include "me32g030_sys.h"
#include "me32g030_ioconfig.h"

extern uint32_t SystemCoreClock;

/*****************************************************************************
Function Name	SYS_IRCTrimto48M
Function Definition	void SYS_SYS_IRCTrimto48M(void)
Function Description	Setup IRC 40Mhz Trim value
Input Parameters	None
Return Value	None
Condition	No
Function called	-

*****************************************************************************/
void SYS_IRCTrimto48M(void)
{
	uint32_t i=0xFFFF;
	if (DIA->IRCTRIM!=0xFFFFFFFF)
	{
		SYSCON->IRCCTRL=DIA->IRCTRIM; 
		SystemCoreClockUpdate ();
	}
	while(i--==0);
}

/*****************************************************************************
Function Name	SYS_SelectMainClkSrc
Function Definition	Void SYS_SelectMainClkSrc(uint8_t src)
Function Description	Select Main clcok source
Input Parameters	src:IRC_CLK
								WDT_CLK
								EXT32K_CLK
Other are invalid
Return Value	No
Condition	No
Function called	-

*****************************************************************************/
void SYS_SelectMainClkSrc(uint8_t src)
{
	//switch main clk source
	SYSCON->MAINCLKUEN_b.ENA= 1;					//disable main clk update
	//switch main clk source to Specifyed source
	if (src==IRC_CLK)
		SYSCON->MAINCLKSEL_b.MAINSEL=0;
	else if (src==WATCHDOG_CLK)
		SYSCON->MAINCLKSEL_b.MAINSEL=1; 
			
	SYSCON->MAINCLKUEN_b.ENA=0; 						//enable main clk update
	
	SystemCoreClockUpdate ();
	return;
}
/*****************************************************************************
Function Name	SYS_SetAHBClkDivider
Function Definition	Void SYS_SetAHBClkDivider (uint8_t div)
Function Description	Set divider, that divides the main clock to provide the system clock to the core, memories,and the peripherals.
Input Parameters	div:1~255, 0 is forbidented
Return Value	No
Condition	No
Function called	-

*****************************************************************************/
void SYS_SetAHBClkDivider (uint8_t div)
{
	//setup flash access speed if SystemCoreClock is going tomore than 30MHz
 	if ((SYSCON->MAINCLKSEL_b.MAINSEL==0)&&(div<2))
 			FMC->FLASH_RDCYC = 1;
	//setup ahb clock divider
	SYSCON->SYSAHBCLKDIV_b.DIV = div;
	//update MainClock and SystemCoreClock
	SystemCoreClockUpdate ();   
	return;
}
/*****************************************************************************
Function Name	SYS_SelectWDTClkSrc
Function Definition	Void SYS_SelectWDTClkSrc(uint8_t src)
Function Description	Select clock source as WDT counter clock.
Input Parameters	src:IRC_CLK
											WDT_CLK
Other are invalid
Return Value	No
Condition	No
Function called	-

*****************************************************************************/
void SYS_SelectWDTClkSrc(uint8_t src)
{
	if (src==IRC_CLK)
		SYSCON->WDTOSCCTRL_b.WDTCLKSRC = 0;
	else if (src==WATCHDOG_CLK)
		SYSCON->WDTOSCCTRL_b.WDTCLKSRC = 1;
 
	return;
}

/*****************************************************************************
Function Name	SYS_SelectClkOutSrc
Function Definition	SYS_SelectClkOutSrc(uint8_t src)
Function Description	Select clock source as clock output
Input Parameters	src:IRC_CLK
											SYS_CLK
											WDT_CLK
											MAIN_CLK
											EXT32K_CLK
Return Value	No
Condition	No
Function called	-

*****************************************************************************/
void SYS_SelectClkOutSrc(uint8_t src)
{
	switch (src)
	{
		case IRC_CLK:
			src=1;
		break;
		case SYS_CLK:
			src=2;
		break;
		case WATCHDOG_CLK:
			src=3;
		break;
		case MAIN_CLK:
			src=4;
		break;
		case EXT32K_CLK:
			src=5;
		break;
		default:
			src=0;
		break;
	}
	//switch clock
	SYSCON->CLKOUTUEN_b.ENA = 1;
	SYSCON->CLKOUTCLKSEL_b.SEL = src; 	//select clk out source
	SYSCON->CLKOUTUEN_b.ENA = 0;
 
	return;
}

/*****************************************************************************
Function Name	SYS_SetClkOutDivider
Function Definition	SYS_SetClkOutDivider(uint16_t src)
Function Description	Select clock source as clock output
Input Parameters	div:Clock output divider, valid 1~255 
											0: clock is disable
Return Value	No
Condition	No
Function called	-

*****************************************************************************/
void SYS_SetClkOutDivider(uint16_t div)
{
	SYSCON->CLKOUTDIV_b.DIV = div;
 
	return;
}

/*****************************************************************************
Function Name	SYS_EnableClkOut
Function Description	Enable clock output
Input Parameters	No
Return Value	No
Condition	No
Function called	-

*****************************************************************************/
void SYS_EnableClkOut(void)
{
	PC13_INIT(PC13_CLKOUT);   							//enable clock out pin 

	return;
}

/*****************************************************************************
Function Name	SYS_DisableClkOut
Function Definition	Void SYS_DisableClkOut(void)
Function Description	Disable clock output
Input Parameters	No
Return Value	No
Condition	No
Function called	-

*****************************************************************************/
void SYS_DisableClkOut(void)
{
	SYSCON->CLKOUTDIV_b.DIV = 0;						//disable clock out
	PC13_INIT(PC13_GPIO);   							//recover IO pin to GPIO 
 
	return;
}

/*****************************************************************************
Function Name	SYS_PowerDownAngIP
Function Definition	SYS_PowerDownAngIP(uint32_t angips)
Function Description	Shut down specific analog IPs power supply
Input Parameters	Angips: analog IPs bit
Valid bit values are PD_IRC, PD_BOD, PD_ADC, PD_WDTOSC, PD_LCD, PD_TOUCH
Return Value	No
Condition	No
Function called	-

*****************************************************************************/
void SYS_PowerDownAngIP(uint32_t angips)
{
	SYSCON->PDRUNCFG |= angips;
 
	return;
}
/*****************************************************************************
Function Name	SYS_PowerUpAngIP
Function Definition	SYS_PowerUpAngIP(uint32_t angips)
Function Description	Power up specific analog IPs power supply
Input Parameters	Angips: analog IPs bit 
Valid bit values are PD_IRC, PD_BOD, PD_ADC,  PD_WDTOSC, PD_LCD, PD_TOUCH
Return Value	No
Condition	No
Function called	-

*****************************************************************************/
void SYS_PowerUpAngIP(uint32_t angips)
{
	SYSCON->PDRUNCFG &= ~angips;
 
	return;
}
/*****************************************************************************
Function Name	SYS_EnablePhrClk
Function Definition	void SYS_EnablePhrClk(uint32_t phrs)
Function Description	Enable specific peripherals clock
Input Parameters	phrs: peripherals clock bit 
Valid bit values are AHB_TWS, AHB_CRC, AHB_TIM0, AHB_TIM1, AHB_TIM6, 
	AHB_TIM7, AHB_SPI, AHB_UART0, AHB_UART1,AHB_ADC, AHB_WDT, AHB_IOCON, 
	AHB_PWM,AHB_LCD, AHB_RTC,AHB_TOUCH 
Return Value	No
Condition	No
Function called	-

*****************************************************************************/
void SYS_EnablePhrClk(uint32_t phrs)
{
	SYSCON->SYSAHBCLKCTRL |= phrs;
 
	return;
}
/*****************************************************************************
Function Name	SYS_DisablePhrClk
Function Definition	void SYS_DisablePhrClk(uint32_t phrs)
Function Description	Disable specific peripherals clock
Input Parameters	phrs: peripherals clock bit 
Valid bit values are AHB_TWS, AHB_CRC, AHB_TIM0, AHB_TIM1, AHB_TIM6, 
AHB_TIM7, AHB_SPI, AHB_UART0, AHB_UART1,AHB_ADC, AHB_WDT, AHB_IOCON, 
AHB_PWM,AHB_LCD, AHB_RTC,AHB_TOUCH 
Return Value	No
Condition	No
Function called	-

*****************************************************************************/
void SYS_DisablePhrClk(uint32_t phrs)
{
	SYSCON->SYSAHBCLKCTRL &= ~phrs;
 
	return;
}
/*****************************************************************************
Function Name	SYS_ResetPhr
Function Definition	void SYS_ResetPhr(uint32_t phrs)
Function Description	Reset specific peripherals 
Input Parameters	phrs: peripherals clock bit 
Valid bit values are RTS_TWS, RST_CRC, RST_TIM0, RST_TIM1,RST_TIM2, RST_TIM3, RST_TIM6, 
RST_TIM7, RST_SPI, RST_UART0, RST_UART1,RST_ADC, RST_WDT, 
RST_IOCON, RST_PWM,RST_LCD, RST_TOUCH 
Return Value	No
Condition	No
Function called	-

*****************************************************************************/
void SYS_ResetPhr(uint32_t phrs)
{
	SYSCON->PRESETCTRL &= ~phrs;
	SYSCON->PRESETCTRL |= phrs;
	return;
}
/*****************************************************************************
Function Name	SYS_ResetSystem
Function Definition	void SYS_ResetSystem(void)
Function Description	Software Reset system
Input Parameters	No
Return Value	No
Condition	No
Function called	-

*****************************************************************************/
void SYS_ResetSystem(void)
{
	NVIC_SystemReset();
}
/*****************************************************************************
Function Name	SYS_BODResetSystem
Function Definition	void SYS_BODResetSystem (uint8_t bodsel)
Function Description	Enable BOD and config BOD Reset option
Input Parameters	Bodsel: 
BOD_ENTER_INT
BOD_EXIT_INT
BOD_RESET
Other values are invalid
Return Value	No
Condition	No
Function called	-

*****************************************************************************/
void SYS_BODResetSystem (uint8_t bodsel)
{
	SYSCON->BODCTRL=0xFF;
	SYSCON->BODCTRL=bodsel|0x1;
	return;
}

/*****************************************************************************
Function Name	SYS_EnterSleep
Function Definition	void SYS_EnterSleep (void)
Function Description	Enter sleep mode
Input Parameters	No
Return Value	No
Condition	No
Function called	-

*****************************************************************************/
void SYS_EnterSleep (void)
{
	//Sleep
	PMU->PCON_b.DPDEN = 0;			//sleep
	SCB->SCR &= ~(1<<2);							//sleep
	
	//issue sleep command
	__WFI();	//enter sleep
	return;
}
void sysdelay(uint32_t ticks)
{
	while(ticks--);
	return;
}
void SYS_EnterDeepSleep (void)
{
	volatile uint32_t loops;
	SYSCON->PDRUNCFG_b.SLDO_PD = 0;
	SYSCON->VREFTRIM = 0xFF;
	SYSCON->PDRUNCFG_b.WDTOSC_PD=0; //power up WDT 32K OSC
	loops=0xFF;
	while(loops--);
	//shutdown analog
	SYSCON->PDRUNCFG_b.BOD_PD=1;

	//mainclock switch to wdt 32k clock
	SYSCON->MAINCLKUEN_b.ENA=1;
	SYSCON->MAINCLKSEL_b.MAINSEL=1;
	SYSCON->MAINCLKUEN_b.ENA=0;
	WDT->MOD_b .WDLOCKDP =1;
	//prepare sleep
	WDT->MOD_b .WDLOCKDP =1;
	PMU->PCON_b.DPDEN = 1;
	SCB->SCR |= (1<<2);	//Power Down	
//	SCB->SCR &= ~(1<<2);							//sleep	
	//issue sleep command
	__WFI();	//enter sleep
	//mainclock switch back to IRC
	SYSCON->PDRUNCFG_b.IRC_PD=0;
	loops=0xFF;
	while(loops--);	
	SYSCON->MAINCLKUEN_b.ENA=1;
	SYSCON->MAINCLKSEL_b.MAINSEL=0;
	SYSCON->MAINCLKUEN_b.ENA=0;
		
	return;
}
/*****************************************************************************
Function Name	SYS_EnterPowerDown
Function Definition	void SYS_EnterPowerDown (void)
Function Description	Enter sleep mode
Input No
Return Value	No
Condition	No
Function called	-

*****************************************************************************/
void SYS_EnterPowerDown(void)
{
	uint32_t wakeup_pin_state,delay_loops=0;
	//wait untile wakeup pin stay at high
	while(delay_loops<0xFF)
	{
		wakeup_pin_state=0;
		if (PB->PIN_b .PIN5)
				wakeup_pin_state=1;
		wakeup_pin_state=wakeup_pin_state<<1;
		if (PC->PIN_b .PIN13)
				wakeup_pin_state|=1;
		wakeup_pin_state=wakeup_pin_state<<1;		
		if (PA->PIN_b .PIN4)
				wakeup_pin_state|=1;
		wakeup_pin_state=wakeup_pin_state<<1;		
		if (PA->PIN_b .PIN2)
				wakeup_pin_state|=1;
		
		if ((wakeup_pin_state & SYSCON->WAKEUPCTRL)==SYSCON->WAKEUPCTRL)
			delay_loops++;
		else
			delay_loops=0;
	}
	//issue Power Down
	PMU->PCON_b.DPDEN = 1;
	SCB->SCR |= (1<<2);	//Power Down	
	__WFI();	//enter power down
}

/*****************************************************************************
Function Name	SYS_Delay
Function Definition	void SYS_Delay(volatile uint32_t loops)
Function Description	Delay 
Input No. of loops
Return Value	No
Condition	No
Function called	-

*****************************************************************************/	
void SYS_Delay(volatile uint32_t loops)
{
	while(loops--!=0);
}

